#pragma once
#include <iostream>
#include <fstream>
#include <vector>
#include "scanner.h"
#include "exp.h"
#include "env.h"



class Parser
{
private:
	Scanner scanner;
	Token* currToken;
	void move(int tagID);
	void stats(std::vector <std::unique_ptr<Stat>>& stats_vector);
	std::unique_ptr<Stat> stat();
	std::unique_ptr<Stat> block();
	std::unique_ptr<Stat> assign_expr(std::unique_ptr<Expr>);
	std::unique_ptr<Stat> local_stat();
	std::unique_ptr<Stat> func_define();
	std::unique_ptr<Stat> ret_stat();
	std::unique_ptr<Stat> br_stat();
	void func_args_list(std::unique_ptr<FuncDefineStat>&);
	std::unique_ptr<Stat> if_stat();
	std::unique_ptr<Stat> when_stat();
	std::unique_ptr<Expr> expr();
	std::unique_ptr<Expr> cmp_exper();
	std::unique_ptr<Expr> _cmp_exper(std::unique_ptr<Expr>);
	std::unique_ptr<Expr> aritch_exper();
	std::unique_ptr<Expr> _aritch_exper(std::unique_ptr<Expr>);
	std::unique_ptr<Expr> multi_expr();
	std::unique_ptr<Expr> _multi_expr(std::unique_ptr<Expr>);
	std::unique_ptr<Expr> unary();
	std::unique_ptr<Expr> _unary();
	std::unique_ptr<Expr> simple_exper();
	std::shared_ptr<FuFuType> type_decl();
	std::shared_ptr<FuFuType> _basic_type_decl();
	std::shared_ptr<FuFuType> _array_type_decl(std::shared_ptr<FuFuType> _basic_type);
	std::unique_ptr<Expr> _array_expr(std::unique_ptr<Expr>);
	std::ofstream dstFile;
	void init_env();
	void args_list(std::vector<std::unique_ptr<Expr>>& args);
	void logic_exper();
public:
	Parser() = default;
	Parser(std::string src);
	void generate(std::string output_file);
};